package com.dji.djiapp.activity;

import androidx.appcompat.app.AppCompatActivity;

import android.annotation.SuppressLint;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
import android.widget.Button;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.dji.djiapp.MApplication;
import com.dji.djiapp.R;
import com.dji.djiapp.config.ModuleVerificationUtil;
import com.dji.djiapp.entity.ControlSignal;
import com.dji.djiapp.websocket.JWebSocketClient;
import com.dji.djiapp.websocket.JWebSocketClientReceiver;
import com.dji.djiapp.websocket.JWebSocketClientService;

import java.util.Timer;
import java.util.TimerTask;

import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import dji.common.error.DJIError;
import dji.common.flightcontroller.FlightOrientationMode;
import dji.common.flightcontroller.virtualstick.FlightControlData;
import dji.common.flightcontroller.virtualstick.FlightCoordinateSystem;
import dji.common.flightcontroller.virtualstick.RollPitchControlMode;
import dji.common.flightcontroller.virtualstick.VerticalControlMode;
import dji.common.flightcontroller.virtualstick.YawControlMode;
import dji.common.gimbal.Rotation;
import dji.common.gimbal.RotationMode;
import dji.common.util.CommonCallbacks;
import dji.keysdk.FlightControllerKey;
import dji.keysdk.KeyManager;
import dji.sdk.flightcontroller.FlightController;

public class OperationActivity extends AppCompatActivity {
    private String TAG = "OperationActivity";
    private Context mContext;
    private JWebSocketClient client;
    private JWebSocketClientService.JWebSocketClientBinder binder;
    private JWebSocketClientService jWebSClientService;
    private JWebSocketClientReceiver chatMessageReceiver;

    private SendVirtualStickDataTask sendVirtualStickDataTask;
    private Timer sendVirtualStickDataTimer;

    private Timer timer;
    private GimbalRotateTimerTask gimbalRotationTimerTask;

    private float pitch;
    private float roll;
    private float yaw;
    private float throttle;
    private FlightControlData flightControlData;
    private FlightControllerKey isSimulatorActived;

    @SuppressLint("NonConstantResourceId")
    @BindView(R.id.flight_control_btn)
    Button flightControlBtn;

    @SuppressLint("NonConstantResourceId")
    @BindView(R.id.tripod_control_btn)
    Button TripodControlBtn;

    @SuppressLint("NonConstantResourceId")
    @BindView(R.id.reset_btn)
    Button resetBtn;

    @SuppressLint("NonConstantResourceId")
    @BindView(R.id.set_btn)
    Button setBtn;

    private ServiceConnection serviceConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
            Log.e(TAG, "服务与活动成功绑定");
            binder = (JWebSocketClientService.JWebSocketClientBinder) iBinder;
            jWebSClientService = binder.getService();
            client = jWebSClientService.client;
        }

        @Override
        public void onServiceDisconnected(ComponentName componentName) {
            Log.e(TAG, "服务与活动成功断开");
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_operation);
        mContext = OperationActivity.this;
        init();
    }

    private void init() {
        ButterKnife.bind(this);
//        //启动服务
//        startJWebSClientService();
//        //绑定服务
//        bindService();
//        //注册广播
//        doRegisterReceiver();
        Boolean isSimulatorOn = (Boolean) KeyManager.getInstance().getValue(isSimulatorActived);
        if (isSimulatorOn != null && isSimulatorOn) {
//            btnSimulator.setChecked(true);
//            textView.setText("Simulator is On.");
        }
        flightControlData = new FlightControlData(0, 0, 0, 0);

    }

    @SuppressLint("NonConstantResourceId")
    @OnClick(R.id.flight_control_btn)
    public void flightControlListener() {
        flightControlData = null;
        Intent intent = new Intent(OperationActivity.this, FlightControlActivity.class);
        startActivity(intent);
    }

    @SuppressLint("NonConstantResourceId")
    @OnClick(R.id.tripod_control_btn)
    public void tripodControlListener() {
        flightControlData = null;
        Intent intent = new Intent(OperationActivity.this, TripodControlActivity.class);
        startActivity(intent);
    }

    @SuppressLint("NonConstantResourceId")
    @OnClick(R.id.reset_btn)
    public void resetListener() {
        flightControlData = null;
        Log.i(TAG, "reset set");
        MApplication.getAircraftInstance()
                .getFlightController().setVirtualStickModeEnabled(true, new CommonCallbacks.CompletionCallback() {
            @Override
            public void onResult(DJIError djiError) {

            }
        });
    }

    @OnClick(R.id.set_btn)
    public void setListener() {
        initControlSetting();
    }

    private void initControlSetting() {
        FlightController flightController = ModuleVerificationUtil.getFlightController();
        if (flightController == null) {
            return;
        }
        Log.i(TAG, "set begin");

        MApplication.getAircraftInstance()
                .getFlightController().setVirtualStickModeEnabled(true, new CommonCallbacks.CompletionCallback() {
            @Override
            public void onResult(DJIError djiError) {

            }
        });
        MApplication.getAircraftInstance()
                .getFlightController().setFlightOrientationMode(FlightOrientationMode.AIRCRAFT_HEADING, new CommonCallbacks.CompletionCallback() {
            @Override
            public void onResult(DJIError djiError) {

            }
        });

        MApplication.getAircraftInstance()
                .getFlightController().setRollPitchCoordinateSystem(FlightCoordinateSystem.BODY);
        MApplication.getAircraftInstance()
                .getFlightController().setRollPitchControlMode(RollPitchControlMode.VELOCITY);
        MApplication.getAircraftInstance()
                .getFlightController().setYawControlMode(YawControlMode.ANGULAR_VELOCITY);
        MApplication.getAircraftInstance()
                .getFlightController().setVerticalControlMode(VerticalControlMode.VELOCITY);
    }

    /**
     * 绑定服务
     */
    private void bindService() {
        Intent bindIntent = new Intent(mContext, JWebSocketClientService.class);
        bindService(bindIntent, serviceConnection, BIND_AUTO_CREATE);
    }

    /**
     * 启动服务（websockets客户端服务）
     */
    private void startJWebSClientService() {
        Intent intent = new Intent(mContext, JWebSocketClientService.class);
        startService(intent);
    }

    /**
     * 动态注册广播
     */
    private void doRegisterReceiver() {
        chatMessageReceiver = new JWebSocketClientReceiver(new JWebSocketClientReceiver.onReceiveListener() {
            @Override
            public void onMessage(String message) {
                JSONObject obj = JSONObject.parseObject(message);
                if (!obj.containsKey("isArtifact") || !obj.containsKey("key")) {
                    return;
                }
                if (obj.getBoolean("isArtifact")) {
                    switch (obj.getString("key")) {
                        case "LeftUp":
                            flightControlData.setVerticalThrottle(2f);
                            break;
                        case "LeftLeft":
                            flightControlData.setYaw(-50f);
                            break;
                        case "LeftDown":
                            flightControlData.setVerticalThrottle(-2f);
                            break;
                        case "LeftRight":
                            flightControlData.setYaw(50f);
                            break;
                        case "RightUp":
                            flightControlData.setRoll(7.5f);
                            break;
                        case "RightLeft":
                            flightControlData.setPitch(-7.5f);
                            break;
                        case "RightDown":
                            flightControlData.setRoll(-7.5f);
                            break;
                        case "RightRight":
                            flightControlData.setPitch(7.5f);
                            break;
                        case "Landing":
                            MApplication.getAircraftInstance()
                                    .getFlightController().startLanding(new CommonCallbacks.CompletionCallback() {
                                @Override
                                public void onResult(DJIError djiError) {

                                }
                            });
                            break;
                        case "Takeoff":
                            MApplication.getAircraftInstance()
                                    .getFlightController().startTakeoff(new CommonCallbacks.CompletionCallback() {
                                @Override
                                public void onResult(DJIError djiError) {

                                }
                            });
                            break;
                        case "KeyUp":
                            flightControlData = new FlightControlData(0,0,0,0);
                            break;
                    }
                } else {
                    switch (obj.getString("key")) {
                        case "Up":
                            if (timer == null) {
                                timer = new Timer();
                                gimbalRotationTimerTask = new GimbalRotateTimerTask(10, Rotation.NO_ROTATION);
                                timer.schedule(gimbalRotationTimerTask, 0, 100);
                            }
                            break;
                        case "Left":
                            if (timer == null) {
                                timer = new Timer();
                                gimbalRotationTimerTask = new GimbalRotateTimerTask( Rotation.NO_ROTATION, -10);
                                timer.schedule(gimbalRotationTimerTask, 0, 100);
                            }
                            break;
                        case "Down":
                            if (timer == null) {
                                timer = new Timer();
                                gimbalRotationTimerTask = new GimbalRotateTimerTask(-10, Rotation.NO_ROTATION);
                                timer.schedule(gimbalRotationTimerTask, 0, 100);
                            }
                            break;
                        case "Right":
                            if (timer == null) {
                                timer = new Timer();
                                gimbalRotationTimerTask = new GimbalRotateTimerTask( Rotation.NO_ROTATION, 10);
                                timer.schedule(gimbalRotationTimerTask, 0, 100);
                            }
                            break;
                        case "KeyUp":
                            stop();
                            break;
                    }
                }

                ControlSignal signal = JSON.parseObject(message, ControlSignal.class);

                if (signal.isLand() || signal.isTakeoff()) {
                    flightControlData = null;
                } else {
                    flightControlData = signal.getFlightControlData();
                    if (null == sendVirtualStickDataTimer) {
                        sendVirtualStickDataTask = new SendVirtualStickDataTask();
                        sendVirtualStickDataTimer = new Timer();
                        sendVirtualStickDataTimer.schedule(sendVirtualStickDataTask, 100, 200);
                    }
                }

                if (signal.isTakeoff()) {
                    if (ModuleVerificationUtil.isFlightControllerAvailable()) {
                        MApplication.getAircraftInstance()
                                .getFlightController().startTakeoff(new CommonCallbacks.CompletionCallback() {
                            @Override
                            public void onResult(DJIError djiError) {

                            }
                        });
                    }
                }

                if (signal.isLand()) {
                    if (ModuleVerificationUtil.isFlightControllerAvailable()) {
                        MApplication.getAircraftInstance()
                                .getFlightController().startLanding(new CommonCallbacks.CompletionCallback() {
                            @Override
                            public void onResult(DJIError djiError) {

                            }
                        });
                    }
                }
            }
        });
        IntentFilter filter = new IntentFilter("com.xch.servicecallback.content");
        registerReceiver(chatMessageReceiver, filter);
    }
    private void stop(){
        if (timer != null) {
            if (gimbalRotationTimerTask != null) {
                gimbalRotationTimerTask.cancel();
            }
            timer.cancel();
            timer.purge();
            gimbalRotationTimerTask = null;
            timer = null;
        }

        if (ModuleVerificationUtil.isGimbalModuleAvailable()) {
            MApplication.getProductInstance().getGimbal().
                    rotate(null, new CommonCallbacks.CompletionCallback() {

                        @Override
                        public void onResult(DJIError error) {

                        }
                    });
        }
    }

    private void initAllKeys() {
        isSimulatorActived = FlightControllerKey.create(FlightControllerKey.IS_SIMULATOR_ACTIVE);
    }


    private class SendVirtualStickDataTask extends TimerTask {

        @Override
        public void run() {
            if (ModuleVerificationUtil.isFlightControllerAvailable()) {
                if (flightControlData != null) {
                    MApplication.getAircraftInstance()
                            .getFlightController()
                            .sendVirtualStickFlightControlData(flightControlData,
                                    new CommonCallbacks.CompletionCallback() {
                                        @Override
                                        public void onResult(DJIError djiError) {
                                            Log.w(TAG, djiError.getDescription());
                                        }
                                    });
                }
            }
        }
    }

    private static class GimbalRotateTimerTask extends TimerTask {
        float pitchValue;
        float yawValue;

        GimbalRotateTimerTask(float pitchValue, float yawValue) {
            super();
            this.pitchValue = pitchValue;
            this.yawValue = yawValue;
        }

        public float getPitchValue() {
            return pitchValue;
        }

        public void setPitchValue(float pitchValue) {
            this.pitchValue = pitchValue;
        }

        public float getYawValue() {
            return yawValue;
        }

        public void setYawValue(float yawValue) {
            this.yawValue = yawValue;
        }

        @Override
        public void run() {
            if (ModuleVerificationUtil.isGimbalModuleAvailable()) {
                MApplication.getProductInstance().getGimbal().
                        rotate(new Rotation.Builder().pitch(pitchValue)
                                .mode(RotationMode.SPEED)
                                .yaw(yawValue)
                                .roll(Rotation.NO_ROTATION)
                                .time(0)
                                .build(), new CommonCallbacks.CompletionCallback() {

                            @Override
                            public void onResult(DJIError error) {

                            }
                        });
            }
        }
    }
}